package com.niodata.dp.util;

import com.niodata.dp.log.LogUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class RedisUtil {

  public static final Logger logger = Logger.getLogger(RedisUtil.class);

  public static boolean saveObject(JedisPool jedisPool, String key, Object object, int expireTime) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      jedis.set(key.getBytes(), SerializeUtil.serialize(object));
      jedis.expire(key.getBytes(), expireTime);
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return true;
  }

  public static boolean savePersistObject(JedisPool jedisPool, String key, Object object) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      jedis.set(key.getBytes(), SerializeUtil.serialize(object));
      jedis.persist(key.getBytes());
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return true;
  }

  public static boolean deleteObject(JedisPool jedisPool, String key) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      jedis.del(key);
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return true;
  }

  /**
   * delete all keys with prefix.
   *
   * @param jedisPool jedis pool
   * @param prefix key prefix
   * @return success
   */
  public static boolean deleteByPrefix(JedisPool jedisPool, String prefix) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      Set<String> keys = jedis.keys(prefix + "*");
      for (String key : keys) {
        jedis.del(key);
      }
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return true;
  }

  /**
   * get object from redis.
   */
  public static Object getObject(JedisPool jedisPool, String key) {
    Object object = null;
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      byte[] bytes = jedis.get(key.getBytes());
      if (bytes != null) {
        object = SerializeUtil.deserialize(bytes);
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return object;
  }


  public static int ttl(JedisPool jedisPool, String key) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      return jedis.ttl(key).intValue();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return -2;
  }

  /**
   * rpop a redis list,return pop result if success,else return null.
   *
   * @param jedisPool jedis pool
   * @param dbIndex dbindex
   * @param key key of the list
   * @return pop result
   */
  public static String rpop(JedisPool jedisPool, Integer dbIndex, String key) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      jedis.select(dbIndex);
      return jedis.rpop(key);
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      jedis.close();
    }
    return null;
  }

  /**
   * pop list by key .
   *
   * @param dbIndex db index
   * @param key key
   * @param timeOut timeout , unit: second
   * @return list
   */
  public static List<String> brpop(JedisPool jedisPool,
        Integer dbIndex, String key, int timeOut) {
    List<String> result = new ArrayList<>();
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      if (null != dbIndex) {
        jedis.select(dbIndex);
      }
      result = jedis.brpop(timeOut, key);
    } catch (Exception e) {
      System.out.println("brpop error：" + e.getMessage());
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return result;
  }

  /**
   * get list length.
   *
   * @param jedisPool jedispool
   * @param dbIndex dbindex
   * @param key key
   * @return length of the key
   */
  public static long llen(JedisPool jedisPool, Integer dbIndex, String key) {
    long result = 0L;
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      if (null != dbIndex) {
        jedis.select(dbIndex);
      }
      result = jedis.llen(key);
    } catch (Exception e) {
      System.out.println("llen error：" + e.getMessage());
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return result;
  }

  public static boolean pushToList(JedisPool jedisPool, String key, String... value) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      long size = jedis.lpush(key, value);
      return size > 0;
    } catch (Exception e) {
      LogUtil.logStackTrace(logger, e);
      return false;
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
  }

  /**
   * blpop from redis.
   */
  public static String blpop(JedisPool jedisPool, String key, int timeout) {
    Jedis jedis = null;
    String value = null;
    try {
      jedis = jedisPool.getResource();
      List<String> values = jedis.blpop(timeout, key);
      if (values != null && values.size() == 2) {
        value = values.get(1);
      }
    } catch (Exception e) {
      LogUtil.logStackTrace(logger, e);
      return null;
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return value;
  }

  /**
   * add value to map.
   */
  public static void hmset(JedisPool jedisPool, String mapName, String key, String value) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      Map<String, String> map = new HashMap<>();
      map.put(key, value);
      jedis.hmset(mapName, map);
    } catch (Exception e) {
      LogUtil.logStackTrace(logger, e);
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
  }

  /**
   * add value to map.
   */
  public static void hmset(JedisPool jedisPool, String mapName, Map<String, String> value) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      jedis.hmset(mapName, value);
    } catch (Exception e) {
      LogUtil.logStackTrace(logger, e);
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
  }

  /**
   * get value from map.
   */
  public static String hmget(JedisPool jedisPool, String mapName, String key) {
    Jedis jedis = null;
    String value = null;
    try {
      jedis = jedisPool.getResource();
      List<String> list = jedis.hmget(mapName, key);
      if (list != null && list.size() > 0) {
        value = list.get(0);
      }
    } catch (Exception e) {
      LogUtil.logStackTrace(logger, e);
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
    return value;
  }


  /**
   * del key of map.
   */
  public static void hdel(JedisPool jedisPool, String mapName, String key) {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
      jedis.hdel(mapName, key);
    } catch (Exception e) {
      LogUtil.logStackTrace(logger, e);
    } finally {
      if (jedis != null) {
        jedis.close();
      }
    }
  }
}
